﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using BrokerBase.Lib.Product;
using System.Diagnostics;

namespace BrokerBase.Lib.Policy
{
    public class PolicyPeriodActing:IPolicyPeriodActing
    {
        private IPolicyActing policyActing;
        private ISchemePeriodActing spa;
        private IDutyActing[] das;

        public PolicyPeriodActing(ISchemePeriodActing spa, IPolicyActing policyActing)
        {
            this.spa = spa;
            this.policyActing = policyActing;

            int n = policyActing.Policy.Product.Duties.Count;
            das = new IDutyActing[n];

            IList<IDuty> orderDuties = policyActing.Policy.Product.Duties.OrderBy(p => p.Sort).ToList();

            for (int i = 0; i < n; i++)
            {
                das[i] = new DutyActing(this, orderDuties[i]);
            }
        }

        public ISchemePeriodActing SchemePeriodActing
        {
            get { return spa; }
        }

        public IPolicyActing PolicyActing 
        {
            get { return policyActing; }
        }

        public int Period { get { return SchemePeriodActing.Period; } }

        public int Age { get { return SchemePeriodActing.Age; } }

        public int Year { get { return SchemePeriodActing.Year; } }

        public bool IsAtPaymentPeriod
        {
            get 
            {
                return Period<policyActing.Policy.PaymentPeriodLength;

            }
        }

        public bool IsAtInsurancePeriod
        {
            get
            {
                return Period < policyActing.Policy.InsurancePeriodLength;

                //switch (policyActing.Policy.SelectedInsurancePeriod.Style)
                //{
                //    case Product.InsurancePeriodStyle.Lifetime:
                //        return true;
                //    case Product.InsurancePeriodStyle.Period:
                //        return spa.Period <= policyActing.Policy.SelectedInsurancePeriod.Value;
                //    case Product.InsurancePeriodStyle.Age:
                //        return spa.Age <= policyActing.Policy.SelectedInsurancePeriod.Value;
                //    default:
                //        throw new Exception("没有匹配的保险期限类型");
                //}
            }
        }

        public bool IsAtCalcPeriod
        {
            get 
            {
                IProduct product=policyActing.Policy.Product;

                int finishPeriod = policyActing.FinishPeriodActing.Period;

                if (product.ProductType == ProductType.Basic)
                {
                    return Period <= finishPeriod;
                }
                else if (product.ProductType == ProductType.Extra)
                {
                    //通过主险名称找到关联记录
                    IRelation bp=product.Relations.First(r=>r.Basic.Name==SchemePeriodActing.SchemeActing.Scheme.Policies[0].Product.Name);

                    if(bp.IsTerminationEqualBasic)//如果设定主险终止，附加险也终止的条件
                        return Period <= finishPeriod && SchemePeriodActing.BasicPolicyPeriodActing.IsAtCalcPeriod;
                    else
                        return Period<=finishPeriod;

                }
                else
                {
                    throw new Exception("没有指定正确的产品的类型!");
                }
            }
        }

        public bool IsCurrentFinish { get; set; }


        public double Amount { get; set; }

        public double Fee { get; set; }

        public double TotalFee
        {
            get
            {
                return policyActing.PeriodActings.Where(p => p.Period <= Period).Sum(s => s.Fee);
            }
        }

        public double Value 
        {
            get
            {
                return DutyActings.Sum(p => p.Value);
            }
        }

        public double TotalValue
        {
            get
            {
                return policyActing.PeriodActings.Where(p => p.Period <= Period).Sum(s => s.Value);
            }
        }

        public double DeductionValue 
        {
            get
            {
                return DutyActings.Where(p => p.IsDeduction).Sum(q => q.Value);
            }
        }

        public double TotalDeductionValue 
        {
            get { return policyActing.PeriodActings.Where(p => p.Period <= Period).Sum(s => s.DeductionValue); }
        }

        public double? CashValue { get; set; }

        public IDutyActing[] DutyActings { get{return das;} }


        public void Calc()
        {
            try
            {
                //重新初始化
                IsCurrentFinish = false;

                Amount = 0;
                Fee = 0;
                
                Tag = null;

                foreach (var da in das)
                {
                    da.Value = 0;
                }
                 
                //Debug.Assert(!(policyActing.Policy.Product.ProductType == ProductType.Extra && Period >10));

                if (IsAtPaymentPeriod)
                {
                    if (Period == 0)
                    {
                        Fee = policyActing.Policy.Fee;
                    }
                    else
                    {
                        double x = policyActing.PeriodActings[Period - 1].Fee;
                        Fee = x <= double.Epsilon ? 0 : policyActing.Policy.Fees[Period];
                    }
                }

                if (IsAtInsurancePeriod)
                {
                    if (Period == 0)
                        Amount = policyActing.Policy.Amount;
                    else
                        Amount = policyActing.PeriodActings[Period - 1].Amount;
                }

                //Debug.Assert(Age != 75);


                foreach (var da in das)
                {
                    da.Value = 0;
                    da.Tag = null;
                    da.Description = null;

                    try
                    {
                        if (da.Duty.Action != null)
                            da.Duty.Action(this, da);
                    }
                    catch (Exception ex)
                    {
                        throw ex;
                    }
                    //Debug.Assert(!(da.Duty.Name == "豁免保险" && SchemePeriodActing.InsurantStates.Contains("重度失能")));


                }

                if (!IsAtCalcPeriod)
                {
                    Amount = 0;
                    Fee = 0;

                    foreach (var d in das)
                    {
                        d.Value = 0;
                    }
                }

            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        public object Tag { get; set; }

        public double GetDutyTotalValue(string name)
        {
            double s = policyActing.PeriodActings.Where(p => p.Period <= Period).Sum(q => q.DutyActings.FirstOrDefault(k => k.Duty.Name == name).Value);

            return s;
        }

        public bool IsLastPeriod 
        {
            get
            {
                if (this.PolicyActing.Policy.SelectedInsurancePeriod.Style != InsurancePeriodStyle.Lifetime)
                {
                    return Period == this.PolicyActing.PeriodActings.Count() - 1;
                }
                else
                {
                    return false;
                }
            }
        }
    }
}
